local desc_1v2 = [[
  # 兵临城下模式简介

  ___

  由手杀斗地主衍生而来，后被手杀斗地主取代。游戏由三人进行，一人扮演城主（主公），其他两人扮演联军（反贼）。

  城主选将框+2，初始体力和手牌+1，且拥有以下一个额外技能：

  - **襄阳**：回合结束时，你可以选择一项：1.执行一个额外的出牌阶段；2.执行一个额外的摸牌阶段。

  - **江陵**：出牌阶段开始时，您可以选择一项：1.此阶段你使用【杀】和普通锦囊牌无次数限制；2.此阶段你使用【杀】和普通锦囊牌可以增加一个目标。

  - **樊城**：限定技，出牌阶段，你可以选择一项：1.本局游戏你使用【杀】对其他角色造成的伤害+1；2.本局游戏你使用【杀】以外的方式对其他角色造成的伤害+1。

  联军互通选将框和手牌但没有抚恤金

  ---

  ##  出兵机制：

  每名玩家在随机派位后预览自己的选将框且可以换将（需在模式设置自行设置次数），
  
  然后根据将面和城池确认是否要出兵抢占城池，

  选择完成后，选择出兵且座次最靠前的玩家占领城池成为城主，

  若无人选择出兵则座次最靠前的玩家自动成为城主。

  ---

  ##  胜利条件：

  ①城主死亡，联军胜利；

  ②前两轮内，两名联军均死亡，城主胜利；

  ③第三轮开始，若两名联军均存活，则只需一名联军死亡，城主便胜利；

  ④若一个联军杀死了另一个联军，城主也胜利。

  ---

  ##  兵尽机制：
  
  若游戏轮数已超过15轮，所有角色须于其回合结束时失去1点体力。

  ---

  ##  特殊说明：
  
  1.此模式的制作参考了当时的专栏、视频以及相关线下产品，如果有不合理之处欢迎向制作者反馈，感谢您的游玩！

  2.换将环节换完后必须点击确认或放弃，不然没办法更新换完后的武将（改了两天根本没办法，还是弃疗了）；

  3.轮换是全局存档机制，要重置存档须手动关闭该设置然后重开一局，退出后即可完成存档重置；
  
  4.特别感谢：祈、庆思书、陈珪，以及其他提供帮助的新月扩展群和逐云阁的群友！
]]

-- Because packages are loaded before gamelogic.lua loaded
-- so we can not directly create subclass of gamelogic in the top of lua
local ty_1v2_getLogic = function()
    local ty_1v2_logic = GameLogic:subclass("ty_1v2_logic")

    function ty_1v2_logic:initialize(room)
      GameLogic.initialize(self, room)
      self.role_table = { nil, nil, { "lord", "rebel", "rebel" }, }
    end

    function ty_1v2_logic:assignRoles()
      local room = self.room
      local n = #room.players
      local roles = self.role_table[n]
      table.shuffle(roles)

      for i = 1, n do
        local p = room.players[i]
        p.role = roles[i]
      end

      local chengzhuskill = { "ty_xiangyang", "ty_jiangling", "ty_fancheng" }
      if room:getSettings("ChangAn") then
        table.insert(chengzhuskill, "ty_changan")
      end
      local round_skill = chengzhuskill
      local skill
      local function getPlayerByScreenName(room, name)
        return table.find(room.players, function(p)
          return p._splayer:getScreenName() == name
        end)
      end

      local croom = room.room
      local cowner = croom:getOwner()
      local owner = getPlayerByScreenName(room, cowner:getScreenName())
      local chengzhu_data = owner:getGlobalSaveState("ChengZhuData")
      if room:getSettings("TakeTurns") then
        if next(chengzhu_data) ~= nil then
          if chengzhu_data then
            local theskills = {}
            for _, sk in ipairs(chengzhuskill) do
              if not table.contains(chengzhu_data, sk) then
              table.insert(theskills, sk)
              end
            end
            if #theskills > 0 then
              chengzhuskill = theskills
            else
              chengzhu_data = {}
            end
          end
        else
          chengzhu_data = {}
        end
        skill = table.random(chengzhuskill)
        table.insert(chengzhu_data, skill)
        owner:saveGlobalState("ChengZhuData", chengzhu_data)
        local unused = {}
        for _, city in ipairs(chengzhuskill) do
          if city ~= skill then
            table.insert(unused, city)
          end
        end
        if #unused == 0 then
          unused = round_skill
        end
        room:setBanner("@[:]UnusedChengchi", unused)
      else
        skill = table.random(chengzhuskill)
        chengzhu_data = {}
        owner:saveGlobalState("ChengZhuData", chengzhu_data)
      end
      for i = 1, 3, 1 do
        local p = room.players[i]
        room:setPlayerMark(p, "chengzhu", skill)
        room:doBroadcastNotify("ShowToast",
          "本局城池为：<font color='red'>" .. Fk:translate(skill) .. "</font>，请准备应战！！！")
      end
      room:setBanner("@[:]skillchengchi", skill)
    end
    function ty_1v2_logic:chooseGenerals()
        local function getOtherPlayers(room, p)
        local ret = table.simpleClone(room.players)
          table.removeOne(ret, p)
          return ret
        end
        local room = self.room ---@type Room
        local lord = room:getLord()
        room:setCurrent(lord)
        local players = room.players
        local generalNum = room:getSettings("generalNum")
        local n = #room.players
        local sortplayers = {}
        for _, p in ipairs(players) do
          table.insert(sortplayers, p)
        end
        local function getPlayerByScreenName(room, name)
          return table.find(room.players, function(p)
            return p._splayer:getScreenName() == name
          end)
        end

        local croom = room.room
        local cowner = croom:getOwner()
        local owner = getPlayerByScreenName(room, cowner:getScreenName())
        local generals_data = owner:getGlobalSaveState("GeneralsData")
        if room:getSettings("TTGeneral") then
          if next(generals_data) ~= nil then
            if generals_data then
              for _,g in ipairs(generals_data) do
                room:findGeneral(g)
              end
            end
          else
            generals_data = {}
          end
          room:setBanner("@[1v2ttg]UsedGeneral", generals_data)
        else
          generals_data = {}
          owner:saveGlobalState("GeneralsData", generals_data)
        end
        local allgenerals = table.map(room.general_pile, function(g) return Fk.generals[g] end)
        local generals = table.map(Fk:getGeneralsRandomly((n * generalNum + 2), allgenerals), Util.NameMapper)
        table.shuffle(generals)
        local ex_generals = {}
        table.insert(ex_generals, generals[#generals])
        table.insert(ex_generals, generals[#generals-1])
        local  pregenerals = {}
        for i = 1, 3 do
          local start_index = (i - 1) * generalNum + 1
          local end_index = i * generalNum + 1
          table.insert(pregenerals, table.slice(generals, start_index, end_index))
        end
        --获取可换的武将
        local function getChange(all_cards, can_change, id)
          local seat = room:getPlayerById(id).seat
          local change = {}
          if seat == 1 then
            change = table.slice(all_cards, 1, can_change + 1)
          else
            change = table.slice(all_cards,can_change * (seat - 1) + 1, can_change * seat + 1)
          end
          return change
        end

        local can_change = room:getSettings("changeGeneralNum") --换将次数
        local all_cards = table.map(Fk:getGeneralsRandomly((can_change * #players), allgenerals, generals), Util.NameMapper)
        table.shuffle(all_cards)
        local req = Request:new(sortplayers, "CustomDialog")
        req.focus_text = "AskForLord"
          for i, p in ipairs(sortplayers) do
            pregenerals[p.id] = pregenerals[i]
            req:setData(p, {
              path = "packages/mamashengde/gamemode/qml/ChooseGeneralWithCanChange.qml",
              data = {
                change = getChange(all_cards, can_change, p.id),
                cards = pregenerals[p.id],  --generals
                num = 1,  --n
                no_c = false, --no_convert
                heg = false, --heg
                type = "askForGeneralsChosen", --rule
                extra = {n = 1}, --extra_data
              },
            })
            req:setDefaultReply(p, 1)
          end
        
        local lords = {}
        for _, p in ipairs(room.players) do
          local result = req:getResult(p)
          if result ~= "" then
              local choice
              local generals = pregenerals[p.id] or {}  -- 默认使用原始列表
              
              -- 处理不同类型的回复
              if type(result) == "number" then
                  -- 原始格式：纯数字选择
                  choice = result
              elseif type(result) == "string" then
                  -- 新格式：字符串包含选择和武将列表
                  if result:find("|") then
                      local parts = result:split("|")
                      choice = tonumber(parts[1])
                      if #parts > 1 then
                          generals = {}
                          for w in parts[2]:gmatch("([^,]+)") do
                              table.insert(generals, w)
                          end
                      end
                  else
                      -- 纯字符串选择（转换为数字）
                      choice = tonumber(result)
                  end
              end
              
              -- 更新预选列表
              pregenerals[p.id] = generals
              
              if choice == 2 then
                  table.insert(lords, p)
              end
          end
        end
        if #lords > 0 then
          local newplayers = {}
          local others = getOtherPlayers(room, lords[1])
            newplayers[1] = lords[1]
            newplayers[2] = others[1]
            newplayers[3] = others[2]
          room.players = newplayers
          self.room:arrangeSeats(newplayers)
        end


        local roles = { "lord", "rebel", "rebel" }
        for i = 1, n do
          local p = room.players[i]
          p.role = roles[i]
          room:setPlayerProperty(p, "role_shown", true)
          room:broadcastProperty(p, "role")
        end
        for _,p in ipairs(room.players) do  --农民通牌
          if p.role == "lord" then
            lord = p
            local nonlord = room:getOtherPlayers(lord)
            nonlord[1]:addBuddy(nonlord[2])
            nonlord[2]:addBuddy(nonlord[1])
          end
        end
        players = room.players
        local lordz
        for _, p in ipairs(players) do
            if p.role == "lord" then
                lordz = p
            end
        end
        room:setCurrent(lordz)
        local nonlord = table.filter(players, function(p)
            return p.id ~= lordz.id
        end)
        local t1 = pregenerals[nonlord[1].id]
        local t2 = pregenerals[nonlord[2].id]
        local chengzhu = pregenerals[lordz.id]
        table.insert(chengzhu, ex_generals[2])
        table.insert(chengzhu, ex_generals[1])  -- 地主多发俩武将
        local data_table = {
          [nonlord[1].id] = {
            friend_id = nonlord[2].id,
            me = t1, friend = t2,
            change = {},
          },
          
          [nonlord[2].id] = {
            friend_id = nonlord[1].id,
            me = t2, friend = t1,
            change = {},
          },
          
          [lordz.id] = {
            change = {},
            cards = chengzhu, num = 1,
            no_c = false, heg = false,
            type = "askForGeneralsChosen",
            extra = {n = 1},
          },
        }
        local game = Fk.mini_games["1v2_rbsel"]
        local req2 = Request:new(players, "MiniGame")
        req2.focus_text = "AskForGeneral"
        req2.receive_decode = false
        req2.timeout = room:getSettings("generalTimeout")

        for _, p in ipairs(nonlord) do
          local data = data_table[p.id]
          p.mini_game_data = { type = "1v2_rbsel", data = data }
          req2:setData(p, p.mini_game_data)
          req2:setDefaultReply(p, game.default_choice and game.default_choice(p, data))
        end

        local data = data_table[lordz.id]
        game = Fk.mini_games["1v2_ldsel"]
        lordz.mini_game_data = { type = "1v2_ldsel", data = data }
        req2:setData(lordz, lordz.mini_game_data)
        req2:setDefaultReply(lordz, game.default_choice and game.default_choice(lordz, data))

        req2:ask()

        for _, p in ipairs(players) do
          p.mini_game_data = nil
        end

        for _, p in ipairs(players) do
          local result = req2:getResult(p)
          if p.id ~= lordz.id then
            room:prepareGeneral(p, result)
          else
            room:prepareGeneral(p, result[1], result[2])
          end
        end

        room:askToChooseKingdom(players)

        for _, p in ipairs(players) do
            room:broadcastProperty(p, "general")
        end
        if room:getSettings("TTGeneral") then
          for _, p in ipairs(players) do
            table.insert(generals_data, p.general)
          end
          owner:saveGlobalState("GeneralsData", generals_data)
        end
    end

    function ty_1v2_logic:attachSkillToPlayers()
        local room = self.room

        local addRoleModSkills = function(player, skillName)
            local skill = Fk.skills[skillName]
            if not skill then
                fk.qCritical("Skill: " .. skillName .. " doesn't exist!")
                return
            end
            if skill:hasTag(Skill.Lord) then
                return
            end
            if skill:hasTag(Skill.AttachedKingdom) and not table.contains(skill:getSkeleton().attached_kingdom, player.kingdom) then
                return
            end
            room:handleAddLoseSkills(player, skillName, nil, false)
        end
        for _, p in ipairs(room.alive_players) do
            for _, s in ipairs(Fk.generals[p.general]:getSkillNameList(false)) do
                addRoleModSkills(p, s)
            end
            if p.role == "lord" then
              local skill = p:getMark("chengzhu")
              room:handleAddLoseSkills(p, skill, nil, false)
            end
        end
    end

    return ty_1v2_logic
end

local ty_1v2_mode = fk.CreateGameMode {
    name = "ty_1v2_mode",
    minPlayer = 3,
    maxPlayer = 3,
    rule = "ty_1v2_gamerule&",
    main_mode = "1v2_mode",
    logic = ty_1v2_getLogic,
    surrender_func = function(self, playedTime)
        local surrenderJudge = { { text = "time limitation: 0.5 min", passed = playedTime >= 20 } }
        if Self.role ~= "lord" then
            table.insert(surrenderJudge, {
                text = "1v2: left you alive",
                passed = #table.filter(Fk:currentRoom().players, function(p)
                    return p.rest > 0 or not p.dead
                end) == 2
            })
        end

        return surrenderJudge
    end,
    winner_getter = function (self, victim)
      if not victim.surrendered and victim.rest > 0 then
        return ""
      end
      local room = victim.room
      local role_map = { ["lord"] = 0, ["rebel"] = 0, }

      for _, p in ipairs(room.players) do
        if not p.surrendered and not (p.dead and p.rest == 0) then
          local role = p.role
          role_map[role] = role_map[role] + 1
        end
      end

      local winner = ""
      if role_map["lord"] == 0 then-- 城主死亡
        winner = "rebel"
      else -- 城主存活
        if role_map["rebel"] == 0 or room:getBanner("RoundCount") > 2 then -- 联军全死或轮数大于2
          winner = "lord"
        else
          return ""
        end
      end

      return winner
    end,
    get_adjusted = function(self, player)
        if player.role == "lord" then
            return { hp = player.hp + 1, maxHp = player.maxHp + 1 }
        end
        return {}
    end,
    reward_punish = function(self, victim, killer)
        local room = victim.room
        if not killer then return end
        if victim ~= killer and victim.role == "rebel" and killer.role == "rebel" then
          room:gameOver("lord")
        end
    end,
    build_draw_pile = function(self)
      local draw, void = GameMode.buildDrawPile(self)
      local blacklist = {
        "supply_shortage", "indulgence", "halberd", "role__wooden_ox",
      }
      local whitelist = {
        "ty__enemy_at_the_gates", "crossing_the_river_in_white", "kicking_while_down", "ty__drowning",
        "catapult",
      }

      for i = #void, 1, -1 do
        local id = void[i]
        local card = Fk:getCardById(id)
        local name = card.name
        if table.contains(whitelist, name) then
          table.remove(void, i)
          table.insert(draw, id)
        end
      end

      for i = #draw, 1, -1 do
        local id = draw[i]
        local card = Fk:getCardById(id)
        local name = card.name
        if table.contains(blacklist, name) then
          table.remove(draw, i)
          table.insert(void, id)
        end
      end

      return draw, void
    end
}

local W = require "ui_emu.preferences"
ty_1v2_mode.ui_settings = {
  W.PreferenceGroup {
    title = "Properties_ty_1v2",
    W.SwitchRow {
      _settingsKey = "ChangAn",
      title = "ty_settings_changan_title",
    },
    W.SwitchRow {
      _settingsKey = "TakeTurns",
      title = "ty_settings_take_turns_title",
    },
    W.SwitchRow {
      _settingsKey = "TTGeneral",
      title = "ty_settings_take_turns_general_title",
    },
    W.SpinRow {
      _settingsKey = "changeGeneralNum",
      title = "ty_settings_change_general_num_title",
      from = 0,
      to = 20,
    },
  },
}

Fk:loadTranslationTable {
    ["Properties_ty_1v2"] = "兵临城下额外配置",
    ["ty_settings_changan_title"] = "开启额外城池：长安",
    ["help: ty_settings_changan_title"] = "摸牌阶段，可以额外获得两张“文和乱武”锦囊牌",
    ["ty_settings_take_turns_title"] = "城池轮换",
    ["help: ty_settings_take_turns_title"] = "开启后，优先抽取未出过的城池（轮完刷新）",
    ["ty_settings_take_turns_general_title"] = "武将轮换",
    ["help: ty_settings_take_turns_general_title"] = "开启后，优先抽取未出过的武将（抽空刷新）",
    ["ty_settings_change_general_num_title"] = "换将次数（每个框仅限一次）",
    ["ty_1v2_mode"] = "兵临城下",
    [":ty_1v2_mode"] = desc_1v2,
    ["@[:]skillchengchi"] = "本局城池",
    ["@[:]UnusedChengchi"] = "未出城池",
    ["@[1v2ttg]UsedGeneral"] = "已用武将",
    ["@[:]growapart"] = "",
    ["GrowApart"] = "联军生隙",
    [":GrowApart"] = "联军出现嫌隙，从此轮开始，当有一位联军死亡城主即可获得胜利。",
    ["@[:]outofammunition"] = "",
    ["OutOfAmmunition"] = "兵尽粮绝",
    [":OutOfAmmunition"] = "兵尽粮绝，从本轮开始，所有角色须于其回合结束时失去1点体力",
    ["AskForLord"] = "确认地主",

    ["time limitation: 0.5 min"] = "游戏时长达到20秒",
    ["1v2: left you alive"] = "仅剩你和地主存活",
}

Fk:addMiniGame{
  name = "1v2_rbsel",
  qml_path = function(player, data)
    return "packages/mamashengde/gamemode/qml/1v2_rbsel"
  end,
  default_choice = function(player, data)
    return data.me[1]
  end,
  update_func = function(player, data)
    local room = player.room
    local d = player.mini_game_data.data
    local friend = room:getPlayerById(d.friend_id)
    friend:doNotify("UpdateMiniGame", data)
  end,
}

Fk:addMiniGame{
  name = "1v2_ldsel",
  qml_path = function(player, data)
    return "packages/mamashengde/gamemode/qml/1v2_ldsel"
  end,
  default_choice = function(player, data) --默认值
    return table.random(data.cards, 1)
  end,
  update_func = function(player, data)
    player:doNotify("UpdateMiniGame", data)
  end,
}

-- 详细描述mark: @[1v2ttg]xxxx
-- 用于设置banner查看已出过的武将
Fk:addQmlMark{
  name = "1v2ttg",
  how_to_show = function(name, value)
    if type(value) == "string" then
      return Fk:translate(value)
    elseif type(value) == "table" then
      return tostring(#value)
    end
    return " "
  end,
  qml_path = "packages/utility/qml/ViewGeneralPile"
}

return ty_1v2_mode